package com.twu.biblioteca;

import com.twu.biblioteca.menu.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;

public class BibliotecaApp {
    private Library library;
    private HashMap<String, MenuItem> menuItems;
    private boolean shouldQuit;
    private UserIO io;
    private UserRepository repository;

    public static void main(String[] args) {
        UserIO io = new AppUserIO();
        (new BibliotecaApp(io)).run();
    }

    public BibliotecaApp(UserIO userIO) {
        library = new Library();
        library.addDefaultBooks();
        library.addDefaultMovies();

        menuItems = new HashMap<String, MenuItem>();
        addMenuItem(new ListBooksMenuItem());
        addMenuItem(new CheckOutBookMenuItem());
        addMenuItem(new ReturnBookMenuItem());
        addMenuItem(new ListMoviesMenuItem());
        addMenuItem(new CheckOutMovieMenuItem());
        addMenuItem(new ReturnMovieMenuItem());
        addMenuItem(new UserInformationMenuItem());
        addMenuItem(new LogInMenuItem());
        addMenuItem(new LogOutMenuItem());
        addMenuItem(new QuitMenuItem());

        io = userIO;

        repository = new UserRepository();
        repository.addDefaultUsers();
    }

    public void addMenuItem(MenuItem item) {
        menuItems.put(item.getMnemonic(), item);
    }

    public void run() {
        io.println("Welcome to Biblioteca!");
        io.println("");

        while (!shouldQuit) {
            runOneLoop();
        }
    }

    public void runOneLoop() {
        printMenu();

        MenuItem choice = promptForMenuChoice();
        io.println("");

        if (choice != null) {
            PostMenuItemAction action = choice.execute(library, io, repository);
            io.println("");

            if (action == PostMenuItemAction.Quit) {
                shouldQuit = true;
            }
        }
    }

    private void printMenu() {
        io.println("Main menu");
        io.println("---------");

        ArrayList<MenuItem> sorted = new ArrayList<MenuItem>(menuItems.values());

        Collections.sort(sorted, new Comparator<MenuItem>() {
            @Override
            public int compare(MenuItem o1, MenuItem o2) {
                return new Integer(o1.getPriority()).compareTo(o2.getPriority());
            }
        });

        for (MenuItem item : sorted) {
            if (item.shouldDisplay(repository.getLoggedInUser())) {
                io.print(item.getMnemonic());
                io.print(": ");
                io.println(item.getName());
            }
        }

        io.println("");
    }

    public MenuItem promptForMenuChoice() {
        io.print("Please select an option from above: ");

        String choice = io.readLine();
        MenuItem chosenItem = menuItems.get(choice);

        if (chosenItem == null) {
            io.println("Select a valid option!");
        }

        return chosenItem;
    }

    public Library getLibrary() {
        return library;
    }

    public UserRepository getUserAuthenticator() {
        return repository;
    }
}
